package com.atguigu.tingshu.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.account.client.UserAccountFeignClient;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.order.OrderDerate;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.helper.SignHelper;
import com.atguigu.tingshu.order.mapper.OrderDerateMapper;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderInfoService;
import com.atguigu.tingshu.order.template.OrderTemplate;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.user.client.VipServiceConfigFeignClient;
import com.atguigu.tingshu.vo.account.AccountLockResultVo;
import com.atguigu.tingshu.vo.account.AccountLockVo;
import com.atguigu.tingshu.vo.order.OrderDerateVo;
import com.atguigu.tingshu.vo.order.OrderDetailVo;
import com.atguigu.tingshu.vo.order.OrderInfoVo;
import com.atguigu.tingshu.vo.order.TradeVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private VipServiceConfigFeignClient vipServiceConfigFeignClient;

    @Resource
    private UserInfoFeignClient userInfoFeignClient;

    @Resource
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Resource
    private TrackInfoFeignClient trackInfoFeignClient;

    @Resource
    private UserAccountFeignClient accountFeignClient;

    @Resource
    private OrderTemplate orderTemplate;

    @Autowired
    private OrderDerateMapper orderDerateMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private KafkaService kafkaService;


    @Override
    public OrderInfoVo trade(TradeVo tradeVo) {
        return orderTemplate.confirm(tradeVo);
    }

    @Transactional
    @Override
    public void submitOrder(OrderInfoVo orderInfoVo) {
        //验证签名
        HashMap hashMap = JSON.parseObject(JSON.toJSONString(orderInfoVo), HashMap.class);
        hashMap.put("payWay", SystemConstant.ORDER_PAY_WAY_WEIXIN);
        SignHelper.checkSign(hashMap);
        //幂等性校验 防止重复提交
        String orderNo = orderInfoVo.getTradeNo();
        Boolean delete = this.redisTemplate.delete(RedisConstant.TRADE_MDX_PREFIX + orderNo);
        //删除失败
        if (!delete) {
            throw new GuiguException(ResultCodeEnum.ORDER_SUBMIT_REPEAT);
        }
        //判断支付类型
        //其他类型支付
        if (!SystemConstant.ORDER_PAY_ACCOUNT.equals(orderInfoVo.getPayWay())) {
            this.saveOrder(orderInfoVo);
            //TODO:非余额支付发送延时消息关闭订单
//            this.delayClient.setAttribute();
            return;//支付流程
        }
        //余额支付
        //获取订单明细信息
        //验余额并锁余额
        Long userId = AuthContextHolder.getUserId();
        AccountLockVo accountLockVo = new AccountLockVo();
        accountLockVo.setOrderNo(orderNo);
        accountLockVo.setAmount(orderInfoVo.getOrderAmount());
        accountLockVo.setUserId(userId);
        List<OrderDetailVo> orderDetailVoList = orderInfoVo.getOrderDetailVoList();
        if (!CollectionUtils.isEmpty(orderDetailVoList)) {
            accountLockVo.setContent(orderDetailVoList.get(0).getItemName());
        }
        Result<AccountLockResultVo> accountLockResultVoResult = this.accountFeignClient.checkLock(accountLockVo);
        if (accountLockResultVoResult == null || accountLockResultVoResult.getData() == null) {
            //验余额锁余额失败
            throw new GuiguException(ResultCodeEnum.ACCOUNT_LOCK_ERROR);
        }
//        int i = 1 / 0;
        try {
            //保存订单
            this.saveOrder(orderInfoVo);
            // kafka发送消息优化 事务提交之后再去扣减余额
            this.kafkaService.sendMsg(KafkaConstant.QUEUE_ACCOUNT_MINUS, orderNo);

          /*  Result result = this.accountFeignClient.reduceAccount(orderNo);
            if (result == null) {
                throw new GuiguException(ResultCodeEnum.ACCOUNT_MINUSLOCK_ERROR);
            } 应该是在订单事务提交之后再去扣减余额*/
        } catch (Exception e) {
            //kafka发送消息解锁余额
            this.kafkaService.sendMsg(KafkaConstant.QUEUE_ACCOUNT_UNLOCK, orderNo);
            throw new RuntimeException(e);
        }
    }

    private void saveOrder(OrderInfoVo orderInfoVo) {
        List<OrderDetailVo> orderDetailVoList = orderInfoVo.getOrderDetailVoList();
        if (CollectionUtils.isEmpty(orderDetailVoList)) {
            throw new GuiguException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //保存订单
        Long userId = AuthContextHolder.getUserId();
        String orderNo = orderInfoVo.getTradeNo();
        String content = orderDetailVoList.get(0).getItemName();
        OrderInfo orderInfo = new OrderInfo();
        BeanUtils.copyProperties(orderInfoVo, orderInfo);
        orderInfo.setUserId(userId);
        orderInfo.setOrderTitle(content);
        orderInfo.setOrderNo(orderNo);
        orderInfo.setOrderStatus(SystemConstant.ORDER_STATUS_UNPAID);
        this.orderInfoMapper.insert(orderInfo);
        //保存订单详情信息
        Long orderId = orderInfo.getId();
        orderDetailVoList.forEach(orderDetailVo -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(orderDetailVo, orderDetail);
            orderDetail.setOrderId(orderId);
            this.orderDetailMapper.insert(orderDetail);
        });

        //保存订单减免信息
        List<OrderDerateVo> orderDerateVoList = orderInfoVo.getOrderDerateVoList();
        if (!CollectionUtils.isEmpty(orderDerateVoList)) {
            orderDerateVoList.forEach(orderDerateVo -> {
                OrderDerate orderDerate = new OrderDerate();
                BeanUtils.copyProperties(orderDerateVo, orderDerate);
                orderDerate.setOrderId(orderId);
                this.orderDerateMapper.insert(orderDerate);
            });
//            int i = 1 / 0;
        }
    }

    @Override
    public void updateOrderStatus(String orderNo, String expect, String target) {
        //根据order查询订单信息
        OrderInfo orderInfo = this.orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNo, orderNo));
        if (orderInfo == null) {
            return;
        }

        //根据orderId查询订单详情
        List<OrderDetail> orderDetails = this.orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, orderInfo.getId()));
        orderInfo.setOrderStatus(target);
        if (CollectionUtils.isEmpty(orderDetails)) {
            return;
        }
        //获取itemId的集合
        List<Long> itemIds = orderDetails.stream().map(orderDetail -> orderDetail.getItemId()).collect(Collectors.toList());
        if (this.orderInfoMapper.update(orderInfo, new LambdaUpdateWrapper<OrderInfo>()
                .eq(OrderInfo::getOrderNo, orderNo)
                .eq(OrderInfo::getOrderStatus, expect)) == 1) {
            UserPaidRecordVo userPaidRecordVo = new UserPaidRecordVo();
            userPaidRecordVo.setUserId(orderInfo.getUserId());
            userPaidRecordVo.setOrderNo(orderNo);
            userPaidRecordVo.setItemType(orderInfo.getItemType());
            userPaidRecordVo.setItemIdList(itemIds);
            this.kafkaService.sendMsg(KafkaConstant.QUEUE_USER_PAY_RECORD, JSON.toJSONString(userPaidRecordVo));
        }
    }


    @Override
    public OrderInfo getOrderInfo(String orderNo) {
        //查询订单信息
        OrderInfo orderInfo = this.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderNo, orderNo));
        if (orderInfo == null) {
            return orderInfo;
        }
        //查询详情
        Long orderId = orderInfo.getId();
        List<OrderDetail> orderDetails = this.orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderId));
        orderInfo.setOrderDetailList(orderDetails);
        //查询订单减免信息
        List<OrderDerate> orderDerates = this.orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderId));
        orderInfo.setOrderDerateList(orderDerates);
        orderInfo.setPayWayName(getPayWayName(orderInfo.getPayWay()));
        orderInfo.setOrderStatusName(getOrderStatusName(orderInfo.getOrderStatus()));

        return orderInfo;
    }

    @Override
    public Page<OrderInfo> findOrderPage(Integer page, Integer limit) {
        Page<OrderInfo> infoPage = this.page(new Page<OrderInfo>(page, limit), new LambdaQueryWrapper<OrderInfo>()
                .eq(OrderInfo::getUserId, AuthContextHolder.getUserId())
                .orderByDesc(OrderInfo::getId));
        if(infoPage == null || CollectionUtils.isEmpty(infoPage.getRecords())){
            return infoPage;
        }
        List<OrderInfo> records = infoPage.getRecords();
        records.forEach(orderInfo->{
            //查询详情
            Long orderId = orderInfo.getId();
            List<OrderDetail> orderDetails = this.orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>().eq(OrderDetail::getOrderId, orderId));
            orderInfo.setOrderDetailList(orderDetails);
            //查询订单减免信息
            List<OrderDerate> orderDerates = this.orderDerateMapper.selectList(new LambdaQueryWrapper<OrderDerate>().eq(OrderDerate::getOrderId, orderId));
            orderInfo.setOrderDerateList(orderDerates);
            orderInfo.setPayWayName(getPayWayName(orderInfo.getPayWay()));
            orderInfo.setOrderStatusName(getOrderStatusName(orderInfo.getOrderStatus()));
        });
        return infoPage;
    }

    private String getOrderStatusName(String orderStatus) {
        switch (orderStatus) {
            case SystemConstant.ORDER_STATUS_PAID: return "已支付";
            case SystemConstant.ORDER_STATUS_UNPAID: return "未支付";
            case SystemConstant.ORDER_STATUS_CANCEL: return "已取消";
        }
        return null;
    }

    private String getPayWayName(String payWay) {
        switch (payWay) {
            case SystemConstant.ORDER_PAY_WAY_WEIXIN: return "微信";
            case SystemConstant.ORDER_PAY_WAY_ALIPAY: return "支付宝";
            case SystemConstant.ORDER_PAY_ACCOUNT: return "账户余额";
        }
        return null;
    }
}
